package org.deri.socializer.com.http;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.deri.socializer.activities.map.DisplayDimensions;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import android.location.Location;

public class HTTPClient {

	
	public int addNewUser(String url, String name, String password, String xmpp_host, String xmpp_resource) {
		name = name.toLowerCase();
		HashMap<String, String> params = new HashMap<String, String>();
		params.put("command", "add_new_user");
		params.put("name", "" + name);
		params.put("password", "" + password);
		params.put("xmpp_host", "" + xmpp_host);
		params.put("xmpp_resource", "" + xmpp_resource);
		
		System.out.println(url + " " + params);
		Document response = sendHttpPostRequest(url, params);
		if (response == null)
			return -1;
		else {
			//System.out.println(response.toString());
			return extractUserId(response);
		}
	}
	
	public int getUserId(String url, String userName) {
		HashMap<String, String> params = new HashMap<String, String>();
		params.put("command", "get_user_id");
		params.put("user", "" + userName);
		
		//System.out.println(url + " " + params);
		Document response = sendHttpPostRequest(url, params);
		if (response == null)
			return -1;
		else {
			//System.out.println(response.toString());
			return extractUserId(response);
		}
	}
	
	
	public int extractUserId(Document domDocument) {
		int id = -1;
		NodeList nodeList = domDocument.getElementsByTagName("result");
		//System.out.println("nodeList.getLength() = " + nodeList.getLength());
        for(int index=0; index < nodeList.getLength(); index++) {
            Node node = nodeList.item(index);
        	if (node.getNodeType() == Node.ELEMENT_NODE) {
        		try {
		    		Element element = (Element) node;
		    		NodeList singleNode = element.getElementsByTagName("id");
	        		id = Integer.parseInt(singleNode.item(0).getFirstChild().getNodeValue().trim());
        		} catch (Exception exc) {
        			continue;
        		}
        	}
        }
        return id; 
	}
	
	
	public void updateLocationGeo(String url, int userID, double latitude, double longitude) {
		HashMap<String, String> params = new HashMap<String, String>();
		params.put("command", "update_user_location_geo");
		params.put("user_id", "" + userID);
		params.put("latitude", "" + latitude);
		params.put("longitude", "" + longitude);
		//System.out.println(url + " " + params);
		sendHttpPostRequest(url, params);
		//System.out.println(response.toString());
	
	}
	
	public ArrayList<Website> getCloseWebsites(String url, DisplayDimensions dim, int limit) {
		HashMap<String, String> params = new HashMap<String, String>();
		params.put("command", "get_close_websites");
		params.put("minLat", "" + dim.getMinLat());
		params.put("maxLat", "" + dim.getMaxLat());
		params.put("minLng", "" + dim.getMinLng());
		params.put("maxLng", "" + dim.getMaxLng());
		params.put("limit", "" + limit);
		
		//System.out.println(url + " " + params);
		Document response = sendHttpPostRequest(url, params);
		if (response == null)
			return new ArrayList<Website>();
		else {
			//System.out.println(response.toString());
			return extractCloseWebsites(response);
		}
	}
	
	public ArrayList<Walker> getCloseWalkers(String url, DisplayDimensions dim, int limit) {
		HashMap<String, String> params = new HashMap<String, String>();
		params.put("command", "get_close_walkers");
		params.put("minLat", "" + dim.getMinLat());
		params.put("maxLat", "" + dim.getMaxLat());
		params.put("minLng", "" + dim.getMinLng());
		params.put("maxLng", "" + dim.getMaxLng());
		params.put("limit", "" + limit);

		//System.out.println(url + " " + params);
		Document response = sendHttpPostRequest(url, params);

		if (response == null)
			return new ArrayList<Walker>();
		else
			return extractCloseWalkers(response);
	}
	
	public ArrayList<Surfer> getCloseSurfers(String url, DisplayDimensions dim, int limit) {
		HashMap<String, String> params = new HashMap<String, String>();
		params.put("command", "get_close_surfers");
		params.put("minLat", "" + dim.getMinLat());
		params.put("maxLat", "" + dim.getMaxLat());
		params.put("minLng", "" + dim.getMinLng());
		params.put("maxLng", "" + dim.getMaxLng());
		params.put("limit", "" + limit);

		Document response = sendHttpPostRequest(url, params);

		if (response == null)
			return new ArrayList<Surfer>();
		else
			return extractCloseSurfers(response);
	}
	
	public ArrayList<Website> getClosestWebsiteGeo(String url, Location location, double distance, int limit) {
		HashMap<String, String> params = new HashMap<String, String>();
		params.put("command", "get_closest_website_geo");
		params.put("lat", "" + location.getLatitude());
		params.put("lng", "" + location.getLongitude());
		params.put("distance", "" + distance);
		params.put("limit", "" + limit);

		Document response = sendHttpPostRequest(url, params);
		//System.out.println(response.toString());
		if (response == null)
			return new ArrayList<Website>();
		else
			return extractCloseWebsites(response);
	}

	public Document sendHttpPostRequest(String url, HashMap<String, String> params) {
	    HttpClient httpClient = new DefaultHttpClient();
	    HttpPost httpPost = new HttpPost(url);
	    BufferedReader in = null;
	    try {
	        // Add your data
	        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
	        Iterator<String> paramIter = params.keySet().iterator();
	        String key;
	        while (paramIter.hasNext()) {
	        	key = paramIter.next();
	        	nameValuePairs.add(new BasicNameValuePair(key, params.get(key)));
	        }
	        httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
	        
	        
	        HttpResponse response = httpClient.execute(httpPost);
	        
	        in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
	        StringBuffer sb = new StringBuffer("");
	        String line = "";
	        String NL = System.getProperty("line.separator");
	        while ((line = in.readLine()) != null) {
	        	sb.append(line + NL);
	        }
            in.close();
            
            String xmlString = sb.toString();
            //System.out.println(xmlString);
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = factory.newDocumentBuilder();
            InputSource inStream = new InputSource();
            inStream.setCharacterStream(new StringReader(xmlString));

            Document doc = db.parse(inStream);
            return doc;
             

	       
	    } catch (IOException e) {
	        // TODO Auto-generated catch block
	    	e.printStackTrace();
	    	return null;
	    } catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		} finally {
	        if (in != null) {
	            try {
	                in.close();
	                } catch (IOException e) {
	                e.printStackTrace();
	            }
	        }
	        
	    }
	} 
	
	
	public ArrayList<Website> extractCloseWebsites(Document domDocument) {
		ArrayList<Website> locations = new ArrayList<Website>();
		NodeList nodeList = domDocument.getElementsByTagName("location");
		//System.out.println("extractCloseWebsites: nodeList.getLength() = " + nodeList.getLength());
        for(int index=0; index < nodeList.getLength(); index++) {
            Node node = nodeList.item(index);
        	if (node.getNodeType() == Node.ELEMENT_NODE) {
        		try {
		    		Element element = (Element) node;
		    		NodeList singleNode = element.getElementsByTagName("name");
	        		String name = singleNode.item(0).getFirstChild().getNodeValue().trim();
	        		singleNode = element.getElementsByTagName("vloc");
	        		String vloc = singleNode.item(0).getFirstChild().getNodeValue().trim();
	        		singleNode = element.getElementsByTagName("url");
	        		String url = singleNode.item(0).getFirstChild().getNodeValue().trim();
	        		singleNode = element.getElementsByTagName("ploc_lat");
	        		double latDouble = Double.parseDouble(singleNode.item(0).getFirstChild().getNodeValue().trim());
	        		int lat = (int) Math.round(latDouble * 1E6);
	        		singleNode = element.getElementsByTagName("ploc_lon");
	        		double lngDouble = Double.parseDouble(singleNode.item(0).getFirstChild().getNodeValue().trim());
	        		int lng = (int) Math.round(lngDouble * 1E6);
	        		locations.add(new Website(name, vloc, url, lat, lng));
        		} catch (Exception exc) {
        			continue;
        		}
        	}
        }
        return locations;
	}
	
	public ArrayList<Walker> extractCloseWalkers(Document domDocument) {
		ArrayList<Walker> locations = new ArrayList<Walker>();
		NodeList nodeList = domDocument.getElementsByTagName("walker");
        for(int index=0; index < nodeList.getLength(); index++) {
            Node node = nodeList.item(index);
        	if (node.getNodeType() == Node.ELEMENT_NODE) {
        		try {
		    		Element element = (Element) node;
		    		NodeList singleNode = element.getElementsByTagName("id");
	        		int id = Integer.parseInt(singleNode.item(0).getFirstChild().getNodeValue().trim());
	        		singleNode = element.getElementsByTagName("name");
	        		String name = singleNode.item(0).getFirstChild().getNodeValue().trim();
	        		singleNode = element.getElementsByTagName("xmpp_host");
	        		String host = singleNode.item(0).getFirstChild().getNodeValue().trim();
	        		singleNode = element.getElementsByTagName("xmpp_resource");
	        		String resource = singleNode.item(0).getFirstChild().getNodeValue().trim();
	        		singleNode = element.getElementsByTagName("ploc_lat");
	        		double latDouble = Double.parseDouble(singleNode.item(0).getFirstChild().getNodeValue().trim());
	        		int lat = (int) Math.round(latDouble * 1E6);
	        		singleNode = element.getElementsByTagName("ploc_lon");
	        		double lngDouble = Double.parseDouble(singleNode.item(0).getFirstChild().getNodeValue().trim());
	        		int lng = (int) Math.round(lngDouble * 1E6);
	        		String jid = name + "@" + host + "/" + resource;
	        		locations.add(new Walker(id, name, jid, lat, lng, 0));
        		} catch (Exception exc) {
        			continue;
        		}
        	}
        }
        return locations;
	}
	
	public ArrayList<Surfer> extractCloseSurfers(Document domDocument) {
		ArrayList<Surfer> locations = new ArrayList<Surfer>();
		NodeList nodeList = domDocument.getElementsByTagName("surfer");
        for(int index=0; index < nodeList.getLength(); index++) {
            Node node = nodeList.item(index);
        	if (node.getNodeType() == Node.ELEMENT_NODE) {
        		try {
		    		Element element = (Element) node;
		    		NodeList singleNode = element.getElementsByTagName("id");
	        		int id = Integer.parseInt(singleNode.item(0).getFirstChild().getNodeValue().trim());
	        		singleNode = element.getElementsByTagName("name");
	        		String name = singleNode.item(0).getFirstChild().getNodeValue().trim();
	        		singleNode = element.getElementsByTagName("xmpp_host");
	        		String host = singleNode.item(0).getFirstChild().getNodeValue().trim();
	        		singleNode = element.getElementsByTagName("xmpp_resource");
	        		String resource = singleNode.item(0).getFirstChild().getNodeValue().trim();
	        		singleNode = element.getElementsByTagName("vloc");
	        		String domain = singleNode.item(0).getFirstChild().getNodeValue().trim();
	        		singleNode = element.getElementsByTagName("ploc_lat");
	        		double latDouble = Double.parseDouble(singleNode.item(0).getFirstChild().getNodeValue().trim());
	        		int lat = (int) Math.round(latDouble * 1E6);
	        		singleNode = element.getElementsByTagName("ploc_lon");
	        		double lngDouble = Double.parseDouble(singleNode.item(0).getFirstChild().getNodeValue().trim());
	        		int lng = (int) Math.round(lngDouble * 1E6);
	        		String jid = name + "@" + host + "/" + resource;
	        		locations.add(new Surfer(id, name, jid, domain, lat, lng));
        		} catch (Exception exc) {
        			continue;
        		}
        	}
        }
        return locations;
	}
}
